package persistence

import (
	"database/sql"
	"fmt"
	"time"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
)

// DatabaseConfig 数据库配置
type DatabaseConfig struct {
	Type       string
	MySQL      MySQLConfig
	PostgreSQL PostgreSQLConfig
}

// MySQLConfig MySQL配置
type MySQLConfig struct {
	Host            string
	Port            int
	Username        string
	Password        string
	Database        string
	MaxIdleConns    int
	MaxOpenConns    int
	ConnMaxLifetime time.Duration
}

// PostgreSQLConfig PostgreSQL配置
type PostgreSQLConfig struct {
	Host            string
	Port            int
	Username        string
	Password        string
	DBName          string
	SSLMode         string
	MaxIdleConns    int
	MaxOpenConns    int
	ConnMaxLifetime time.Duration
}

// Database 数据库连接
type Database struct {
	*sql.DB
}

// NewDatabase 创建数据库连接
func NewDatabase(config DatabaseConfig) (*Database, error) {
	var dsn string
	var driver string

	switch config.Type {
	case "mysql":
		driver = "mysql"
		dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
			config.MySQL.Username,
			config.MySQL.Password,
			config.MySQL.Host,
			config.MySQL.Port,
			config.MySQL.Database,
		)
	case "postgres":
		driver = "postgres"
		dsn = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
			config.PostgreSQL.Host,
			config.PostgreSQL.Port,
			config.PostgreSQL.Username,
			config.PostgreSQL.Password,
			config.PostgreSQL.DBName,
			config.PostgreSQL.SSLMode,
		)
	default:
		return nil, fmt.Errorf("不支持的数据库类型: %s", config.Type)
	}

	db, err := sql.Open(driver, dsn)
	if err != nil {
		return nil, fmt.Errorf("连接数据库失败: %v", err)
	}

	// 设置连接池参数
	if config.Type == "mysql" {
		db.SetMaxIdleConns(config.MySQL.MaxIdleConns)
		db.SetMaxOpenConns(config.MySQL.MaxOpenConns)
		db.SetConnMaxLifetime(config.MySQL.ConnMaxLifetime)
	} else {
		db.SetMaxIdleConns(config.PostgreSQL.MaxIdleConns)
		db.SetMaxOpenConns(config.PostgreSQL.MaxOpenConns)
		db.SetConnMaxLifetime(config.PostgreSQL.ConnMaxLifetime)
	}

	// 测试连接
	if err := db.Ping(); err != nil {
		return nil, fmt.Errorf("测试数据库连接失败: %v", err)
	}

	return &Database{db}, nil
}
